package customerEnter.Frame.redis.MemoryModel;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.Set;

import customerEnter.Frame.Utils.Log4j;
import customerEnter.Frame.Utils.WhetherToClass;
import customerEnter.Frame.redis.Major.RedisClient;
import customerEnter.tool.WhetherToEmpty;

/**
 * 內存模型管理
 * 
 * 类名称：MemoryModel 类描述： 创建人：dy 创建时间：2016-10-19 上午11:13:00
 * 
 */
public class RedisMemoryModel {
	/**
	 * 模型名字
	 */
	private String redisModelName;
	/**
	 * 模型字段類
	 */
	private Class<?> modelBean;
	/**
	 * 模型反射字段
	 */
	private Field[] fields;
	/**
	 * 模型對應的字段
	 */
	private Map<Object, Object> map;

	/**
	 * 
	 * 初始化 MemoryModel.
	 * 
	 * @param redisModelName
	 * @param modelBean
	 * @throws Exception
	 */
	public RedisMemoryModel(String redisModelName, Class<?> modelBean)
			throws Exception {
		this.redisModelName = redisModelName;
		this.modelBean = modelBean;
		this.fields = modelBean.getDeclaredFields();
		queryRedisModl();
		if (!WhetherToEmpty.ObjectWhetherToEmpty(map)) {
			IfRedisModel();
		}
	}
	
	/**
	 * 設置hash表的過期時間
	 */
	public void SetRedisExpire(){
		for(Field field : fields){
			field.setAccessible(true);
			if("serialVersionUID".equals(field.getName())){
				continue;
			}
			String key_id = "table_" + redisModelName + "_" + field.getName();
			RedisClient.getRedisTemplate().expire(key_id,24 * 365,TimeUnit.HOURS);
		}
	}
	/**
	 * 創建一個 redis 內存模型 （模擬一張數據表） 必須要一個主鍵（id） 屬性不支持list 等集合
	 */

	public void createRedisModel() {
		for (Field field : fields) {
			field.setAccessible(true);
			if ("serialVersionUID".equals(field.getName())) {
				continue;
			}
			RedisClient
					.getRedisTemplate()
					.opsForHash()
					.put(redisModelName, field.getName(),
							"table_" + redisModelName + "_" + field.getName());
		}

	}

	/**
	 * 添加數據 map 格式
	 */

	public void addRedisModelValue(Object object) throws Exception {
		int idObject = findredisModelBean(object);
		String idString = Integer.toString(idObject);
		for (Field field : object.getClass().getDeclaredFields()) {
			if ("serialVersionUID".equals(field.getName())) {
				continue;
			} else {
				field.setAccessible(true);
				String name = map.get(field.getName()).toString();
				String valueString = "";
				try {
					valueString = field.get(object).toString();
				} catch (Exception e) {
					System.out.println("屬性：" + field.getName() + "  "
							+ e.getMessage());
				}
				RedisClient.getRedisTemplate().opsForHash()
						.put(name, idString, valueString);
				
			}
		}
	}
	
	public void updateRedisModelvalue(Object object) throws Exception {
		int idObject = findredisModelBean(object);
		for (Field field : object.getClass().getDeclaredFields()) {
			if ("serialVersionUID".equals(field.getName())) {
				continue;
			} else {
				field.setAccessible(true);
				String name = map.get(field.getName()).toString();  
				String idString = Integer.toString(idObject);	
				String valueString = "";
				try {
					valueString = field.get(object).toString();
					if (WhetherToEmpty.StringWhetherToEmpty(valueString)
							|| valueString.equals(0)) {
						continue;
					}
				} catch (Exception e) {
					System.out.println("屬性：" + field.getName() + "  "
							+ e.getMessage());
				}
				RedisClient.getRedisTemplate().opsForHash()
						.put(name, idString, valueString);
			}
		}
	}
	
	/**
	 * update
	 * 
	 * 傳入key（字段名），id，value
	 * @param <T>
	 */
	public <T> void updateRedisModelOneValue(String key,String id,T value) throws Exception{
		String key_id = RedisClient.getRedisTemplate().opsForHash()
				.get(redisModelName, key).toString();
		String valueStr = null;
		try{
			String typeName = value.getClass().getName();
			if(WhetherToClass.IfIntOrInteger(typeName)){
				valueStr = value + "";
			}else if(WhetherToClass.IfBigDecimal(typeName)){
				valueStr = value.toString();
			}else if(WhetherToClass.IfString(typeName)){
				valueStr = value.toString();
			}
		}catch (Exception e) {
			// TODO: handle exception
			Log4j.Log4JOutError("無法轉為String");
		}
		RedisClient.getRedisTemplate().opsForHash()
				.put(key_id, id, valueStr);
	}
	
	/**
	 * 根據模型名字和id查詢數據
	 * 
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public <T> T queryRedisModelVlaue(String idFind) throws Exception {
		Object object;
		try {
			object = modelBean.newInstance();
		} catch (Exception e) {
			throw new Exception("實例化 bean失敗");
		}
		for (Field field : object.getClass().getDeclaredFields()) {
			field.setAccessible(true);
			if ("serialVersionUID".equals(field.getName())) {
				continue;
			} else {
				Object value = RedisClient.getRedisTemplate().opsForHash()
						.get(map.get(field.getName()).toString(), idFind);
				String type = field.getType().getName();
				try {

					if (WhetherToClass.IfIntOrInteger(type)) {
						if (WhetherToEmpty.ObjectWhetherToEmpty(value)) {
							value = 0;
						}
						String val = value + "".toString();
						field.set(object, Integer.parseInt(val));
					} else if (WhetherToClass.IfString(type)) {
						field.set(object, value);
					} else if (WhetherToClass.IfBigDecimal(type)){ //金額類型，BigDecimal
						BigDecimal bigDecimal = new BigDecimal(value.toString());
						field.set(object, bigDecimal);
					}

				} catch (Exception e) {
					Log4j.Log4JOutError("賦值失敗:" + field.getName() + "___"
							+ e.getMessage());
				}

			}
		}
		return (T) object;
	}

	
//	/**
//	 * 根據模型名字和value查詢id
//	 */
//	public List<Object> queryRedisModelByValue(String valueFind) throws Exception {
//		// key_id是結構名,table_userfair_userid
//		//valueFind是value（string）
//		Object object;
//		String key_id = RedisClient.getRedisTemplate().opsForHash()
//				.get(redisModelName, "userid").toString();
//		List<String> list = new ArrayList<String>();
//		List<Object> redisModelList = new ArrayList<Object>();
//		
//		try{
//			object = modelBean.newInstance();
//		}
//		catch(Exception e){
//			throw new Exception("實例化 bean失敗");
//		}
//		
//		for (Field field : object.getClass().getDeclaredFields()) {
//			field.setAccessible(true); // 實例中有private屬性的變量
//			if(field.getName().equals("userid")){
//				Map<Object,Object> maps = RedisClient.getRedisTemplate().opsForHash().entries(key_id);			//entries可以獲得field = value
//				for(Entry<Object, Object> entry : maps.entrySet()){
//					if(valueFind.equals(entry.getValue())){
//						list.add((String) entry.getKey());
//					}
//				}
//			}
//		}
//		
//		for(String idFind : list){
//			redisModelList.add(queryRedisModelVlaue(idFind));
//		}
//		return redisModelList;
//	}

	/**
	 * 查询多少条数据 (查找的是id索引)
	 */
	public List<Object> queryListRedisModel(int size, int page) {
		// key_id是結構名、表名
		String key_id = RedisClient.getRedisTemplate().opsForHash()
				.get(redisModelName, "id").toString();
		Set<Object> modelValue = RedisClient.getRedisTemplate().opsForHash()
				.keys(key_id);
		List<Object> list = new ArrayList<Object>();
		int bagen = size * page;
		int stop = (size * page) + size;
		int i = 0;
		for (Object object : modelValue) {
			if (i > bagen && i < stop) {
				list.add(object);
			}
			i++;
		}
		return list;
	}

	/**
	 * 根據模型名字 和id 刪除數據
	 */
	public void deleteRedisModelData(String id) throws Exception {
		for (Entry<Object, Object> entry : map.entrySet()) {
//			刪除整個model
//			RedisClient.getRedisTemplate().opsForHash()
//					.delete(redisModelName, entry.getKey());
			RedisClient.getRedisTemplate().opsForHash()
					.delete(entry.getValue().toString(), id);
		}
	}

	/**
	 * 查找內存模型 如果有就返回集合
	 */
	public void queryRedisModl() {
		this.map = RedisClient.getRedisTemplate().opsForHash()
				.entries(redisModelName);
	}

	/**
	 * 檢測內存模型和bean 是否正確
	 * 
	 * @throws Exception
	 */
	public void IfRedisModel() throws Exception {
		if (WhetherToEmpty.ObjectWhetherToEmpty(map)) {
			throw new Exception("Redis內存模型中 沒有這個model");
		} else {
			for (Field field : fields) {
				if ("serialVersionUID".equals(field.getName())) {
					continue;
				} else if (WhetherToEmpty.ObjectWhetherToEmpty(map.get(field
						.getName()))) {
					throw new Exception("bean的 屬性 錯誤:" + field.getName());
				}
			}
		}
	}

	public int findredisModelBean(Object object) throws Exception {
		int idObject = 0;
		for (Field field : object.getClass().getDeclaredFields()) {
			if ("id".equals(field.getName())) {
				field.setAccessible(true);
				try {
					idObject = (Integer) field.get(object);
				} catch (Exception e) {
					throw new Exception(e.getMessage());
				}
			}
		}
		if (idObject == 0) {
			throw new Exception("id不能為空 或者bean中沒有id屬性，id屬性在內存模型中不能缺少");
		}
		return idObject;
	}


}
